/**
 * 
 */
package ro.dta.idbi.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.border.Border;

import ro.dta.idbi.interfaces.ui.IMainFrame;
import ro.dta.idbi.interfaces.ui.IProjectPane;
import ro.dta.idbi.model.SaveStrategyEps;
import ro.dta.idbi.model.SaveStrategyPng;
import ro.dta.idbi.model.SaveStrategyXml;
import uk.ac.ic.doc.automed.reps.Schema;
import uk.ac.ic.doc.automed.reps.Transformation;

import com.mxgraph.model.mxGraphModel;

/**
 * Integration strategy panel for creating an integration strategy
 * 
 * @author Tudor Dobrila
 * 
 */
public class StrategyPanel extends JPanel {

	private static final long serialVersionUID = -3889624775151612477L;

	/**
	 * Parent frame of the application
	 */
	protected final transient IMainFrame parentFrame;

	/**
	 * Project pane containing the strategy panel
	 */
	protected final transient IProjectPane projectPane;

	/**
	 * Strategy diagram
	 */
	protected transient StrategyDiagram diagram;

	/**
	 * Model for the schemas combo box
	 */
	protected final transient DefaultComboBoxModel<String> schemasModel;

	/**
	 * Integration strategy panel class constructor
	 * 
	 * @param parentFrame
	 *            Parent frame of the application
	 */
	public StrategyPanel(final IMainFrame parentFrame) {
		this(parentFrame, null, new mxGraphModel());
	}

	/**
	 * Integration strategy panel class constructor
	 * 
	 * @param parentFrame
	 *            Parent frame of the application
	 * @param projectPane
	 *            Project pane containing the current project
	 */
	public StrategyPanel(final IMainFrame parentFrame, final IProjectPane projectPane) {
		this(parentFrame, projectPane, new mxGraphModel());
	}

	/**
	 * Integration strategy class constructor with initial strategy
	 * 
	 * @param parentFrame
	 *            Parent frame of the application
	 * @param strategy
	 *            Initial strategy
	 */
	public StrategyPanel(final IMainFrame parentFrame, final IProjectPane projectPane,
			final mxGraphModel strategy) {
		super();
		this.parentFrame = parentFrame;
		this.projectPane = projectPane;

		setLayout(new BorderLayout());

		diagram = new StrategyDiagram(parentFrame, strategy);
		add(diagram, BorderLayout.CENTER);

		final JToolBar topPanel = new JToolBar();
		topPanel.setFloatable(false);
		final Border outer = BorderFactory.createLineBorder(Color.GRAY);
		final Border inner = BorderFactory.createEmptyBorder(5, 5, 5, 5);
		topPanel.setBorder(BorderFactory.createCompoundBorder(outer, inner));

		// Schemas list
		final JLabel dispLabel = new JLabel("Schemas List: ");
		topPanel.add(dispLabel);

		schemasModel = new DefaultComboBoxModel<String>();
		updateSchemasBox(false);
		final JComboBox<String> schemasBox = new JComboBox<String>(schemasModel);
		schemasBox.setMaximumSize(schemasBox.getPreferredSize());
		schemasBox.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
		topPanel.add(schemasBox);

		final JButton addBtn = new JButton("Add schema");
		addBtn.setToolTipText("Add schema to the integration strategy");
		addBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(final ActionEvent event) {
				diagram.addSchema(schemasBox.getSelectedItem().toString());
			}
		});
		topPanel.add(addBtn);

		final JCheckBox checkBox = new JCheckBox("Show only data sources / end of pathways schemas");
		checkBox.setSelected(true);
		checkBox.setOpaque(false);
		checkBox.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				updateSchemasBox(!checkBox.isSelected());

			}
		});
		topPanel.add(checkBox);

		topPanel.add(new JSeparator(JSeparator.VERTICAL));

		// Load strategy button
		final JButton loadBtn = new JButton(new ImageIcon("./resources/open_small.png"));
		loadBtn.setToolTipText("Load a strategy from the disk");
		loadBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(final ActionEvent event) {
				diagram.importXML();
			}
		});
		topPanel.add(loadBtn);

		// Save strategy button
		final JButton saveBtn = new JButton(new ImageIcon("./resources/save_small.png"));
		saveBtn.setToolTipText("Save strategy to disk");
		saveBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(final ActionEvent event) {
				diagram.save(new SaveStrategyXml());
			}
		});
		topPanel.add(saveBtn);

		// Export as image button
		final JButton exportBtn = new JButton(new ImageIcon("./resources/png_small.png"));
		exportBtn.setToolTipText("Export strategy as PNG file");
		exportBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(final ActionEvent event) {
				diagram.save(new SaveStrategyPng());
			}
		});
		topPanel.add(exportBtn);

		// Export as image button
		final JButton epsBtn = new JButton(new ImageIcon("./resources/eps.png"));
		epsBtn.setToolTipText("Export strategy as EPS file");
		epsBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(final ActionEvent event) {
				diagram.save(new SaveStrategyEps());
			}
		});
		topPanel.add(epsBtn);

		// Proceed button
		if (projectPane != null) {
			final JButton proceedBtn = new JButton("Proceed");
			proceedBtn.setForeground(new Color(0, 89, 156));
			proceedBtn.setIcon(new ImageIcon("./resources/proceed.png"));
			proceedBtn.setPreferredSize(new Dimension(110, proceedBtn.getHeight()));
			proceedBtn.setToolTipText("Proceed to the next integration phase");
			proceedBtn.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(final ActionEvent event) {
					if (diagram.verifyStrategy()) {
						final int result = JOptionPane.showConfirmDialog(StrategyPanel.this,
								"Are you sure you want to proceed to the integration phase?",
								"Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
						if (result == JOptionPane.YES_OPTION) {
							projectPane.getProject().setStrategy(diagram.getModel());
							projectPane.next();
						}
					} else {
						JOptionPane
								.showMessageDialog(
										StrategyPanel.this,
										"Please enter names for all intermediate schemas in order to proceed to the next phase.",
										"Warning", JOptionPane.WARNING_MESSAGE);
					}
				}
			});
			topPanel.add(proceedBtn);
		}

		add(topPanel, BorderLayout.NORTH);

	}

	/**
	 * Update the elements in the schemas box
	 * 
	 * @param showAll
	 *            True if all schemas should be displayed, false if only data
	 *            source or end of pathway schemas should be displayed
	 */
	private void updateSchemasBox(boolean showAll) {
		Schema[] schemas = Schema.getSchemas();
		schemasModel.removeAllElements();

		for (Schema s : schemas) {
			boolean endPathway = true;
			for (Transformation t : s.getTransformations()) {
				if (t.getSchemas()[0].equals(s)) {
					endPathway = false;
				}
			}

			if (showAll || (!showAll && endPathway)) {
				schemasModel.addElement(s.getName());
			}
		}
	}
}
